﻿using MongoDB.Driver;
using Newtonsoft.Json;
using Sustainalytics.Claims;
using Sustainalytics.DataLayer;
using Sustainalytics.Entities;
using Sustainalytics.Entities.SustainableProducts;
using Sustainalytics.ProductInvolvement.BL;
using Sustainalytics.ScreeningTool.BL;
using Sustainalytics.ScreeningTool.BL.Exceptions;
using Sustainalytics.ScreeningTool.BL.Model;
using Sustainalytics.ScreeningTool.Service.Models;
using Sustainalytics.ScreeningTool.Service.Utility;
using Sustainalytics.Utils;
using Sustainalytics.Utils.Serilog;
using Sustainalytics.Utils.WebApi.ErrorCodes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Cors;

namespace Sustainalytics.ScreeningTool.Service
{
    [EnableCors(origins: "*", headers: "*", methods: "*")]
    //[AutoInvalidateCacheOutput]
    [RoutePrefix("api/v1/filters/{filterId}/criteria")]
    //[ClaimsChecker("api/v1/filters/{filterId}/criteria")]
    public class FilterCriteriaController : ApiController, IFilterCriteriaController
    {
        private readonly ICompanyScreening _companyScreening;
        private readonly IFilterManager _filterManager;
        private readonly IFilterCriteriaManager _filterCriteriaManager;
        private readonly IAccountsRepository _accountsRepository;
        private readonly IProductInvolvementBussinesLogic _productInvolvementBusinessLogic;
        private readonly IMongoCollection<ResultOutput> _resultOutputCollection;
        private readonly IMongoCollection<SustainableProductsFramework> _sustainableProductFramework;
        private readonly IClaimsChecker _claimsChecker;

        public FilterCriteriaController(
            IClaimsChecker claimsChecker,
            ICompanyScreening companyScreening,
            IFilterManager filterManager,
            IFilterCriteriaManager filterCriteriaManager,
            IProductInvolvementBussinesLogic productInvolvementBussinesLogic,
            IAccountsRepository accountsRepository,
            IMongoCollection<ResultOutput> resultOutputCollection,
            IMongoCollection<SustainableProductsFramework> sustainableProductFramework)
        {
            try
            {
                _resultOutputCollection = resultOutputCollection;
                _claimsChecker = claimsChecker;
                _companyScreening = companyScreening;
                _filterManager = filterManager;
                _filterCriteriaManager = filterCriteriaManager;
                _accountsRepository = accountsRepository;
                _productInvolvementBusinessLogic = productInvolvementBussinesLogic;
                _sustainableProductFramework = sustainableProductFramework;
            }
            catch (Exception ex)
            {
                throw new HttpResponseException(HttpStatusCode.InternalServerError);
            }
        }

        //[CacheOutput(ServerTimeSpan = 100, ClientTimeSpan = 0, NoCache = true, MustRevalidate = true, Private = true)]
        [Route("")]
        public HttpResponseMessage Get([FromUri] Guid filterId)
        {
            HttpResponseMessage response;
            List<FilterCriteria> listFilterCriteria;

            try
            {
                if (!_claimsChecker.ValidateAnyShortName(this))
                {
                    throw new FilterCriteriaClaimNullException();
                }

                listFilterCriteria = _filterCriteriaManager.GetAllFilterCriteriaByFilterId(filterId);
                response = Request.CreateResponse(HttpStatusCode.OK, listFilterCriteria);
            }
            catch (FilterCriteriaClaimNullException)
            {
                return Request.CreateResponse(HttpStatusCode.Forbidden);
            }
            catch (Exception ex)
            {
                response = Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
            }
            return response;
        }

        [Route("{id}")]
        public HttpResponseMessage Get([FromUri] Guid filterId, Guid id)
        {
            var response = (HttpResponseMessage)null;

            List<FilterCriteria> listFilterCriteria;
            List<TemplateCriteria> listTemplateCriteria;
            try
            {
                if (!_claimsChecker.ValidateAnyShortName(this))
                {
                    throw new FilterCriteriaClaimNullException();
                }

                var userName = this.GetCurrentUserName();
                if (userName == null)
                    throw CustomExceptionBuilder.CreateUserNotAuthenticated();

                var currentUser = _accountsRepository.GetUserByUsername(userName);
                if (currentUser == null)
                    throw new UnknownUserException(userName);

                listFilterCriteria = _filterCriteriaManager.GetFilterCriteriaGroupByFilterCriteriaId(id);
                if (listFilterCriteria.Count > 0)
                {
                    SelectedCriteriaDto selectedCriteria = new SelectedCriteriaDto();
                    switch (listFilterCriteria[0].CriteriaType)
                    {
                        case CriteriaTypeEnum.CriteriaType1:
                            selectedCriteria = SelectedCriteriaDto.ConvertCriteriaTypeOneToSelectedCriteriaDto(listFilterCriteria[0]);
                            break;

                        case CriteriaTypeEnum.CriteriaType2:
                            listTemplateCriteria = _companyScreening.ListTemplateCriteriaByLevel3Id(listFilterCriteria[0].CriteriaLevel3Id);
                            selectedCriteria = SelectedCriteriaDto.ConvertCriteriaTypeTwoToSelectedCriteriaDto(listFilterCriteria, listTemplateCriteria);
                            break;

                        case CriteriaTypeEnum.CriteriaType3:
                            listTemplateCriteria = _companyScreening.ListTemplateCriteriaByLevel3Id(listFilterCriteria[0].CriteriaLevel3Id);
                            selectedCriteria = SelectedCriteriaDto.ConvertCriteriaTypeThreeToSelectedCriteriaDto(listFilterCriteria, listTemplateCriteria);
                            break;
                        case CriteriaTypeEnum.CriteriaType4:
                            string symbol = ((listFilterCriteria[0].CriteriaEntityField).Split(' '))[0];
                            List<CriteriaTypeFourCategories> finalCategories = new List<CriteriaTypeFourCategories>();

                            var spCategories = _sustainableProductFramework
                                .Find(x => x.Symbol == symbol)
                                .Project(x => x.Categories)
                                .ToList()
                                .SelectMany(x => x)
                                .ToList();

                            if (spCategories.Any())
                            {
                                spCategories.ForEach(cat =>
                                {
                                    Guid templateCriteriaId = _productInvolvementBusinessLogic.GetTemplateCriteriaIdByPISymbol(cat.Symbol);
                                    FilterCriteria currentFilterCriteria = listFilterCriteria.FirstOrDefault(x => x.TemplateCriteriaId == templateCriteriaId);

                                    finalCategories.Add(CriteriaTypeFourCategories.CreateComplete(cat, templateCriteriaId, currentFilterCriteria));
                                });
                            }
                            else
                            {
                                List<Entities.ProductInvolvement.ProductInvolvementCategory> piCategories = _productInvolvementBusinessLogic.GetIndicatorCategories(symbol).ToList();
                                piCategories.ForEach(cat =>
                                {
                                    Guid templateCriteriaId = _productInvolvementBusinessLogic.GetTemplateCriteriaIdByPISymbol(cat.Symbol);
                                    FilterCriteria currentFilterCriteria = listFilterCriteria.FirstOrDefault(x => x.TemplateCriteriaId == templateCriteriaId);

                                    finalCategories.Add(CriteriaTypeFourCategories.CreateComplete(cat, templateCriteriaId, currentFilterCriteria));
                                });
                            }

                            listTemplateCriteria = _companyScreening.ListTemplateCriteriaByLevel3Id(listFilterCriteria[0].CriteriaLevel3Id);
                            CriteriaLevel3 criteriaLevel3 = _companyScreening.GetCriteriaLevelThree(listFilterCriteria[0].CriteriaLevel3Id);
                            selectedCriteria = SelectedCriteriaDto.ConvertCriteriaTypeFourToSelectedCriteriaDto(listFilterCriteria, listTemplateCriteria, criteriaLevel3.Name);

                            selectedCriteria.TypeFourCategories = finalCategories;
                            selectedCriteria.TypeFourSymbol = symbol;
                            break;

                        case CriteriaTypeEnum.CriteriaType5:
                            listTemplateCriteria = _companyScreening.ListTemplateCriteriaByLevel3Id(listFilterCriteria[0].CriteriaLevel3Id);
                            selectedCriteria = SelectedCriteriaDto.ConvertCriteriaTypeFiveToSelectedCriteriaDto(listFilterCriteria, listTemplateCriteria, _companyScreening);
                            break;

                        case CriteriaTypeEnum.CriteriaType6:
                            listTemplateCriteria = _companyScreening.ListTemplateCriteriaByLevel3Id(listFilterCriteria[0].CriteriaLevel3Id);
                            selectedCriteria = SelectedCriteriaDto.ConvertCriteriaTypeSixToSelectedCriteriaDto(listFilterCriteria, listTemplateCriteria);
                            break;

                        case CriteriaTypeEnum.CriteriaType7:
                            listTemplateCriteria = _companyScreening.ListTemplateCriteriaByLevel3Id(listFilterCriteria[0].CriteriaLevel3Id);
                            selectedCriteria = SelectedCriteriaDto.ConvertCriteriaTypeSevenToSelectedCriteriaDto(listFilterCriteria, listTemplateCriteria);
                            break;

                        case CriteriaTypeEnum.CriteriaType8:
                            listTemplateCriteria = _companyScreening.ListTemplateCriteriaByLevel3Id(listFilterCriteria[0].CriteriaLevel3Id);
                            selectedCriteria = SelectedCriteriaDto.ConvertCriteriaTypeEightToSelectedCriteriaDto(listFilterCriteria, listTemplateCriteria);
                            break;

                        case CriteriaTypeEnum.CriteriaType9:
                            listTemplateCriteria = _companyScreening.ListTemplateCriteriaByLevel3Id(listFilterCriteria[0].CriteriaLevel3Id);
                            selectedCriteria = SelectedCriteriaDto.ConvertCriteriaTypeNineToSelectedCriteriaDto(listFilterCriteria, listTemplateCriteria);
                            break;

                        case CriteriaTypeEnum.CriteriaType10:
                            listTemplateCriteria = _companyScreening.ListTemplateCriteriaByLevel3Id(listFilterCriteria[0].CriteriaLevel3Id);
                            selectedCriteria = SelectedCriteriaDto.ConvertCriteriaTypeTenToSelectedCriteriaDto(listFilterCriteria, listTemplateCriteria);
                            break;

                        case CriteriaTypeEnum.CriteriaType16:
                            listTemplateCriteria = _companyScreening.ListTemplateCriteriaByLevel3Id(listFilterCriteria[0].CriteriaLevel3Id);
                            selectedCriteria = SelectedCriteriaDto.ConvertCriteriaType16ToSelectedCriteriaDto(listFilterCriteria, listTemplateCriteria);
                            break;

                        case CriteriaTypeEnum.CriteriaType17:
                            listTemplateCriteria = _companyScreening.ListTemplateCriteriaByLevel3Id(listFilterCriteria[0].CriteriaLevel3Id);
                            selectedCriteria = SelectedCriteriaDto.ConvertCriteriaType17ToSelectedCriteriaDto(listFilterCriteria, listTemplateCriteria, _companyScreening);
                            break;

                        case CriteriaTypeEnum.CriteriaType25:
                            listTemplateCriteria = _companyScreening.ListTemplateCriteriaByLevel3Id(listFilterCriteria[0].CriteriaLevel3Id);
                            selectedCriteria = SelectedCriteriaDto.ConvertCriteriaType25ToSelectedCriteriaDto(listFilterCriteria, listTemplateCriteria, _companyScreening);
                            break;
                    }
                    selectedCriteria.CriteriaLevel3Id = listFilterCriteria[0].CriteriaLevel3Id;
                    response = Request.CreateResponse(HttpStatusCode.OK, selectedCriteria);
                }
            }
            catch (FilterCriteriaClaimNullException)
            {
                return Request.CreateResponse(HttpStatusCode.Forbidden);
            }
            catch (UnknownUserException ex)
            {
                response = Request.CreateResponse(HttpStatusCode.Unauthorized,
                                                 new
                                                 {
                                                     ErrorStatusCode = WebAPIGeneralErrorCodes.UserNotFound,
                                                     Details = new { resourceId = filterId }
                                                 });
            }
            catch (Exception ex)
            {
                response = Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
            }

            return response;
        }

        [Route("{criteriaId}/collection/{collectionName}/content")]
        [HttpGet]
        public HttpResponseMessage Get(string collectionName, [FromUri] ListOptions listOptions, string collItemsNameLike)
        {
            try
            {
                List<CriteriaBasicDto> basicCriteriaDtos = new List<CriteriaBasicDto>();

                CriteriaTypeThree criteriaTypeThreeItem = _companyScreening.LoadCriteriaTypeThreeSingleCollection(collectionName);

                List<CriteriaBasic> criteriaItemsList = _companyScreening.LoadCriteriaTypeThreeDataSingleItems(criteriaTypeThreeItem);

                if (criteriaItemsList != null && criteriaItemsList.Any())
                {
                    foreach (CriteriaBasic criteriaBasicItem in criteriaItemsList)
                    {
                        basicCriteriaDtos.Add(new CriteriaBasicDto() { Id = criteriaBasicItem.Id, Name = criteriaBasicItem.Name, IntId = criteriaBasicItem.IntId });
                    }
                }

                if (!string.IsNullOrEmpty(collItemsNameLike))
                {
                    basicCriteriaDtos = basicCriteriaDtos.Where(items => items.Name.ToLowerInvariant().Contains(collItemsNameLike.ToLowerInvariant())).ToList();
                }

                if (listOptions.Skip != 0 && listOptions.Take != 0)
                {
                    basicCriteriaDtos = basicCriteriaDtos.Skip(listOptions.Skip).Take(listOptions.Take).ToList();
                }

                return Request.CreateResponse(HttpStatusCode.OK, basicCriteriaDtos);
            }
            catch (AuthorizationException)
            {
                return Request.CreateResponse(HttpStatusCode.Unauthorized);
            }
            catch (Exception)
            {
                return Request.CreateResponse(HttpStatusCode.NotFound, new { Code = ErrorCodes.ScreeningTool_LoadingCriteriaTabs });
            }
        }

        [Route("")]
        public HttpResponseMessage Post([FromUri] Guid filterId, [FromBody] object dto)
        {
            HttpResponseMessage response;
            var result = new List<FilterCriteria>();

            try
            {
                var userName = this.GetCurrentUserName();

                var currentUser = _accountsRepository.GetUserByUsername(userName);
                if (currentUser == null)
                    throw new UnknownUserException(userName);

                var filter = _filterManager.LoadFilter(filterId, userName);

                FilterCriteria filterCriteria;
                var isReport = filter.TargetType != 0;

                Guid filterGroupId;

                var allFilterCriteriaToAdd = JsonConvert.DeserializeObject<List<string>>(dto.ToString());

                foreach (var item in allFilterCriteriaToAdd)
                {
                    var definition = new { type = 0, criteriaLevel2Id = Guid.Empty };
                    var baseFilterCriteria = JsonConvert.DeserializeAnonymousType(item, definition);

                    //Validates the current filter criteria
                    var criteriaLevel2 = _companyScreening.GetCriteriaLevelTwo(baseFilterCriteria.criteriaLevel2Id);
                    ValidateShortName(criteriaLevel2.ShortName);

                    switch (baseFilterCriteria.type)
                    {
                        case 1:
                            if (!isReport)
                            {
                                var criteriaTypeOneDefinition = new CriteriaTypeOneDto();
                                var criteriaTypeOne = JsonConvert.DeserializeAnonymousType(item.ToString(), criteriaTypeOneDefinition);

                                filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeOne(criteriaTypeOne.Id, filterId, isReport, criteriaTypeOne.MinValue, criteriaTypeOne.MaxValue);
                                result.Add(filterCriteria);
                            }
                            else
                            {
                                var criteriaTypeOneDefinition = new CriteriaTypeIsNotScreenable();
                                var criteriaTypeOne = JsonConvert.DeserializeAnonymousType(item.ToString(), criteriaTypeOneDefinition);

                                if (criteriaTypeOne.IsOn)
                                {
                                    filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeOne(criteriaTypeOne.Id, filterId, isReport, null, null);
                                    result.Add(filterCriteria);
                                }
                                //else
                                //{
                                //    _filterCriteriaManager.DeleteFilterCriteriaByIdTemplateIdAndFilterId(criteriaTypeOne.Id, filterId);
                                //}
                            }
                            break;

                        case 2:
                            filterGroupId = Guid.NewGuid();
                            var criteriaTypeTwoDefinition = new CriteriaTypeTwoDto();
                            var criteriaTypeTwo = JsonConvert.DeserializeAnonymousType(item.ToString(), criteriaTypeTwoDefinition);

                            if (criteriaTypeTwo.IsScreenableCriteriaItems != null)
                            {
                                foreach (var itemScreenable in criteriaTypeTwo.IsScreenableCriteriaItems)
                                {
                                    if (itemScreenable.Score > 0)
                                    {
                                        filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeTwo(itemScreenable.Id, filterId, filterGroupId, isReport, itemScreenable.Score);
                                        result.Add(filterCriteria);
                                    }
                                    //else
                                    //{
                                    //    if (isReport)
                                    //    {
                                    //        _filterCriteriaManager.DeleteFilterCriteriaByIdTemplateIdAndFilterId(itemScreenable.Id, filterId);
                                    //    }
                                    //}
                                }
                            }
                            if (criteriaTypeTwo.IsNotScreenableCriteriaItems != null)
                            {
                                foreach (var itemNotScreenable in criteriaTypeTwo.IsNotScreenableCriteriaItems)
                                {
                                    if (itemNotScreenable.IsOn)
                                    {
                                        filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeTwo(itemNotScreenable.Id, filterId, filterGroupId, isReport, null);
                                        result.Add(filterCriteria);
                                    }
                                    //else
                                    //{   //delete filterCriteria
                                    //    if (isReport)
                                    //    {
                                    //        _filterCriteriaManager.DeleteFilterCriteriaByIdTemplateIdAndFilterId(itemNotScreenable.Id, filterId);
                                    //    }
                                    //}
                                }
                            }
                            break;

                        case 3:
                            var criteriaTypeThreeValidation = JsonConvert.DeserializeAnonymousType(item.ToString(), new CriteriaTypeIsNotScreenable());

                            //ShortName (claim name) is hard coded as criteria type name for Sedol, wkn, Valor
                            var claimNames = new[] { "sedol", "wkn", "valor" };
                            if (!string.IsNullOrWhiteSpace(criteriaTypeThreeValidation.Name) && claimNames.Contains(criteriaTypeThreeValidation.Name.ToLowerInvariant()))
                                ValidateShortName(criteriaTypeThreeValidation.Name);

                            filterGroupId = Guid.NewGuid();
                            var criteriaTypeThreeDefinition = new CriteriaTypeThreeDto();
                            var criteriaTypeThree = JsonConvert.DeserializeAnonymousType(item.ToString(), criteriaTypeThreeDefinition);

                            if (criteriaTypeThree.IsScreenableCriteriaItems != null)
                            {
                                foreach (var itemScreenable in criteriaTypeThree.IsScreenableCriteriaItems)
                                {
                                    if (!string.IsNullOrWhiteSpace(itemScreenable.Name) && claimNames.Contains(itemScreenable.Name.ToLowerInvariant()))
                                        ValidateShortName(itemScreenable.Name);

                                    if (itemScreenable.SelectedItems != null && itemScreenable.SelectedItems.Count > 0)
                                    {
                                        filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeThree(itemScreenable.Id, filterId, isReport, itemScreenable.SelectedItems, filterGroupId);
                                        result.Add(filterCriteria);
                                    }
                                    //else
                                    //{
                                    //    if (isReport)
                                    //    {
                                    //        _filterCriteriaManager.DeleteFilterCriteriaByIdTemplateIdAndFilterId(itemScreenable.Id, filterId);
                                    //    }
                                    //}
                                }
                            }

                            if (criteriaTypeThree.IsNotScreenableCriteriaItems != null)
                            {
                                foreach (var itemNotScreenable in criteriaTypeThree.IsNotScreenableCriteriaItems)
                                {
                                    if (!string.IsNullOrWhiteSpace(itemNotScreenable.Name) && claimNames.Contains(itemNotScreenable.Name.ToLowerInvariant()))
                                        ValidateShortName(itemNotScreenable.Name);

                                    if (itemNotScreenable.IsOn)
                                    {
                                        filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeThree(itemNotScreenable.Id, filterId, isReport, null, filterGroupId);
                                        result.Add(filterCriteria);
                                    }
                                    //else
                                    //{
                                    //    if (isReport)
                                    //    {
                                    //        _filterCriteriaManager.DeleteFilterCriteriaByIdTemplateIdAndFilterId(itemNotScreenable.Id, filterId);
                                    //    }
                                    //}
                                }
                            }
                            break;

                        case 4:
                            filterGroupId = Guid.NewGuid();
                            var criteriaTypeFourDefinition = new CriteriaTypeFourDto();
                            var criteriaTypeFour = JsonConvert.DeserializeAnonymousType(item.ToString(), criteriaTypeFourDefinition);

                            ValidateClaimSymbol(criteriaTypeFour.ClaimSymbol);

                            if (criteriaTypeFour.SelectedCategories != null)
                            {
                                foreach (var category in criteriaTypeFour.SelectedCategories)
                                {
                                    result.Add(_filterCriteriaManager.AddAndUpdateCriteriaTypeFour(
                                        category.Id,
                                        filterId,
                                        isReport,
                                        category.CategoryOfInvolvement,
                                        filterGroupId,
                                        category.CategorySymbol,
                                        category.IsInvolvement,
                                        category.IsSignificantOwnership,
                                        category.RevenueRange,
                                        category.Start,
                                        category.Stop));
                                }
                            }

                            if (criteriaTypeFour.IsNotScreenableCriteriaItems != null)
                            {
                                foreach (var itemNotScreenable in criteriaTypeFour.IsNotScreenableCriteriaItems)
                                {
                                    if (itemNotScreenable.IsOn)
                                    {
                                        filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeFour(
                                            itemNotScreenable.Id,
                                            filterId,
                                            isReport,
                                            null,//CategoryOfInvolvement
                                            filterGroupId,
                                            null,//CategorySymbol
                                            null,//IsInvolvement
                                            null,//IsSignificantOwnership
                                            null,//RevenueRange
                                            null,//Start
                                            null);//Stop
                                        result.Add(filterCriteria);
                                    }
                                    //else
                                    //{   //delete filterCriteria
                                    //    if (isReport)
                                    //    {
                                    //        _filterCriteriaManager.DeleteFilterCriteriaByIdTemplateIdAndFilterId(itemNotScreenable.Id, filterId);
                                    //    }
                                    //}
                                }
                            }
                            break;

                        case 5:
                            filterGroupId = Guid.NewGuid();

                            var criteriaTypeFiveDefinition = new CriteriaTypeFiveDto();
                            var criteriaTypeFive = JsonConvert.DeserializeAnonymousType(item.ToString(), criteriaTypeFiveDefinition);

                            if (criteriaTypeFive.IsScreenableCriteriaItems != null)
                            {
                                foreach (var itemScreenable in criteriaTypeFive.IsScreenableCriteriaItems)
                                {
                                    if (itemScreenable.Score >= 0)
                                    {
                                        filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeFive(itemScreenable.Id, filterId, filterGroupId, isReport, itemScreenable.Score);
                                        result.Add(filterCriteria);
                                    }
                                    //else
                                    //{
                                    //    if (isReport)
                                    //    {
                                    //        _filterCriteriaManager.DeleteFilterCriteriaByIdTemplateIdAndFilterId(itemScreenable.Id, filterId);
                                    //    }
                                    //}
                                }
                            }
                            if (criteriaTypeFive.IsNotScreenableCriteriaItems != null)
                            {
                                foreach (var itemNotScreenable in criteriaTypeFive.IsNotScreenableCriteriaItems)
                                {
                                    if (itemNotScreenable.IsOn)
                                    {
                                        filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeFive(itemNotScreenable.Id, filterId, filterGroupId, isReport, null);
                                        result.Add(filterCriteria);
                                    }
                                    //else
                                    //{   //delete filterCriteria
                                    //    if (isReport)
                                    //    {
                                    //        _filterCriteriaManager.DeleteFilterCriteriaByIdTemplateIdAndFilterId(itemNotScreenable.Id, filterId);
                                    //    }
                                    //}
                                }
                            }
                            break;

                        case 6:
                            filterGroupId = Guid.NewGuid();

                            var criteriaTypeSixDefinition = new CriteriaTypeSixDto();
                            var criteriaTypeSix = JsonConvert.DeserializeAnonymousType(item.ToString(), criteriaTypeSixDefinition);

                            if ((!isReport && criteriaTypeSix.Id != Guid.Empty) && !criteriaTypeSix.Removed)
                            {
                                filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeSix(criteriaTypeSix.Id,
                                    filterId, filterGroupId, isReport, criteriaTypeSix.MinValue, criteriaTypeSix.MaxValue);
                                result.Add(filterCriteria);
                            }

                            if (criteriaTypeSix.IsNotScreenableCriteriaItems != null)
                            {
                                foreach (var itemNotScreenable in criteriaTypeSix.IsNotScreenableCriteriaItems)
                                {
                                    if (itemNotScreenable.IsOn)
                                    {
                                        filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeSix(itemNotScreenable.Id, filterId, filterGroupId, isReport, null, null);
                                        result.Add(filterCriteria);
                                    }
                                    //else
                                    //{   //delete filterCriteria
                                    //    if (isReport)
                                    //    {
                                    //        _filterCriteriaManager.DeleteFilterCriteriaByIdTemplateIdAndFilterId(itemNotScreenable.Id, filterId);
                                    //    }
                                    //}
                                }
                            }
                            break;

                        case 7:
                            filterGroupId = Guid.NewGuid();

                            var criteriaTypeSevenDefinition = new CriteriaTypeSevenDto();
                            var criteriaTypeSeven = JsonConvert.DeserializeAnonymousType(item.ToString(), criteriaTypeSevenDefinition);

                            if (criteriaTypeSeven.IsScreenableCriteriaItems != null)
                            {
                                foreach (var itemScreenable in criteriaTypeSeven.IsScreenableCriteriaItems)
                                {
                                    if (itemScreenable.SelectedItems.Count > 0)
                                    {
                                        ValidateGlobalCompact(itemScreenable.SelectedItems);
                                        filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeSeven(itemScreenable.Id, filterId, filterGroupId, isReport, itemScreenable.SelectedItems);
                                        result.Add(filterCriteria);
                                    }
                                    //else
                                    //{
                                    //    if (isReport)
                                    //    {
                                    //        _filterCriteriaManager.DeleteFilterCriteriaByIdTemplateIdAndFilterId(itemScreenable.Id, filterId);
                                    //    }
                                    //}
                                }
                            }
                            if (criteriaTypeSeven.IsNotScreenableCriteriaItems != null)
                            {
                                foreach (var itemNotScreenable in criteriaTypeSeven.IsNotScreenableCriteriaItems)
                                {
                                    if (itemNotScreenable.IsOn)
                                    {
                                        filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeSeven(itemNotScreenable.Id, filterId, filterGroupId, isReport, null);
                                        result.Add(filterCriteria);
                                    }
                                    //else
                                    //{   //delete filterCriteria
                                    //    if (isReport)
                                    //    {
                                    //        _filterCriteriaManager.DeleteFilterCriteriaByIdTemplateIdAndFilterId(itemNotScreenable.Id, filterId);
                                    //    }
                                    //}
                                }
                            }
                            break;

                        case 8:
                            filterGroupId = Guid.NewGuid();

                            var criteriaTypeEightDefinition = new CriteriaTypeEightDto();
                            var criteriaTypeEight = JsonConvert.DeserializeAnonymousType(item.ToString(), criteriaTypeEightDefinition);

                            if (criteriaTypeEight.IsScreenableCriteriaItems != null)
                            {
                                foreach (var itemScreenable in criteriaTypeEight.IsScreenableCriteriaItems)
                                {
                                    if (itemScreenable.Score > 0)
                                    {
                                        filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeEight(itemScreenable.Id, filterId, filterGroupId, isReport, itemScreenable.Score);

                                        result.Add(filterCriteria);
                                    }
                                    //else
                                    //{
                                    //    if (isReport)
                                    //    {
                                    //        _filterCriteriaManager.DeleteFilterCriteriaByIdTemplateIdAndFilterId(itemScreenable.Id, filterId);
                                    //    }
                                    //}
                                }
                            }
                            if (criteriaTypeEight.IsNotScreenableCriteriaItems != null)
                            {
                                foreach (var itemNotScreenable in criteriaTypeEight.IsNotScreenableCriteriaItems)
                                {
                                    if (itemNotScreenable.IsOn)
                                    {
                                        filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeEight(itemNotScreenable.Id, filterId, filterGroupId, isReport, null);

                                        result.Add(filterCriteria);
                                    }
                                    //else
                                    //{   //delete filterCriteria
                                    //    if (isReport)
                                    //    {
                                    //        _filterCriteriaManager.DeleteFilterCriteriaByIdTemplateIdAndFilterId(itemNotScreenable.Id, filterId);
                                    //    }
                                    //}
                                }
                            }
                            break;

                        case 9:
                            filterGroupId = Guid.NewGuid();

                            var criteriaTypeNineDefinition = new CriteriaTypeNineDto();
                            var criteriaTypeNine = JsonConvert.DeserializeAnonymousType(item.ToString(), criteriaTypeNineDefinition);

                            if (criteriaTypeNine.IsScreenableCriteriaItems != null)
                            {
                                foreach (var itemScreenable in criteriaTypeNine.IsScreenableCriteriaItems)
                                {
                                    if (itemScreenable.Score > 0)
                                    {
                                        filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeNine(itemScreenable.Id, filterId, filterGroupId, isReport, itemScreenable.Score);
                                        result.Add(filterCriteria);
                                    }
                                    //else
                                    //{
                                    //    if (isReport)
                                    //    {
                                    //        _filterCriteriaManager.DeleteFilterCriteriaByIdTemplateIdAndFilterId(itemScreenable.Id, filterId);
                                    //    }
                                    //}
                                }
                            }
                            if (criteriaTypeNine.IsNotScreenableCriteriaItems != null)
                            {
                                foreach (var itemNotScreenable in criteriaTypeNine.IsNotScreenableCriteriaItems)
                                {
                                    if (itemNotScreenable.IsOn)
                                    {
                                        filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeNine(itemNotScreenable.Id, filterId, filterGroupId, isReport, null);
                                        result.Add(filterCriteria);
                                    }
                                    //else
                                    //{   //delete filterCriteria
                                    //    if (isReport)
                                    //    {
                                    //        _filterCriteriaManager.DeleteFilterCriteriaByIdTemplateIdAndFilterId(itemNotScreenable.Id, filterId);
                                    //    }
                                    //}
                                }
                            }
                            break;

                        case 10:
                            filterGroupId = Guid.NewGuid();

                            var criteriaTypeTenDefinition = new CriteriaTypeTenDto();
                            var criteriaTypeTen = JsonConvert.DeserializeAnonymousType(item.ToString(), criteriaTypeTenDefinition);

                            if (criteriaTypeTen.IsNotScreenableCriteriaItems != null)
                            {
                                foreach (var itemNotScreenable in criteriaTypeTen.IsNotScreenableCriteriaItems)
                                {
                                    if (itemNotScreenable.IsOn)
                                    {
                                        filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeTen(itemNotScreenable.Id, filterId, filterGroupId, isReport/*, null*/);
                                        result.Add(filterCriteria);
                                    }
                                    //else
                                    //{   //delete filterCriteria
                                    //    if (isReport)
                                    //    {
                                    //        _filterCriteriaManager.DeleteFilterCriteriaByIdTemplateIdAndFilterId(itemNotScreenable.Id, filterId);
                                    //    }
                                    //}
                                }
                            }
                            break;

                        case 16:
                            filterGroupId = Guid.NewGuid();

                            var criteriaType16Definition = new CriteriaType16Dto();
                            var criteriaType16 = JsonConvert.DeserializeAnonymousType(item.ToString(), criteriaType16Definition);

                            if (!isReport && !criteriaType16.Removed)
                            {
                                filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaType16(criteriaType16.Id,
                                    filterId, filterGroupId, isReport, criteriaType16.MinValue, criteriaType16.MaxValue);
                                result.Add(filterCriteria);
                            }

                            if (criteriaType16.IsNotScreenableCriteriaItems != null)
                            {
                                foreach (var itemNotScreenable in criteriaType16.IsNotScreenableCriteriaItems)
                                {
                                    if (itemNotScreenable.IsOn)
                                    {
                                        filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaType16(itemNotScreenable.Id, filterId, filterGroupId, isReport, null, null);
                                        result.Add(filterCriteria);
                                    }
                                    //else
                                    //{   //delete filterCriteria
                                    //    if (isReport)
                                    //    {
                                    //        _filterCriteriaManager.DeleteFilterCriteriaByIdTemplateIdAndFilterId(itemNotScreenable.Id, filterId);
                                    //    }
                                    //}
                                }
                            }
                            break;

                        case 17:
                            filterGroupId = Guid.NewGuid();

                            var criteriaType17Definition = new CriteriaType17Dto();
                            var criteriaType17 = JsonConvert.DeserializeAnonymousType(item.ToString(), criteriaType17Definition);

                            if (criteriaType17.IsScreenableCriteriaItems != null)
                            {
                                foreach (var itemScreenable in criteriaType17.IsScreenableCriteriaItems)
                                {
                                    if (itemScreenable.Score >= 0)
                                    {
                                        filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaType17(itemScreenable.Id, filterId, filterGroupId, isReport, itemScreenable.Score);
                                        result.Add(filterCriteria);
                                    }
                                    //else
                                    //{
                                    //    if (isReport)
                                    //    {
                                    //        _filterCriteriaManager.DeleteFilterCriteriaByIdTemplateIdAndFilterId(itemScreenable.Id, filterId);
                                    //    }
                                    //}
                                }
                            }
                            if (criteriaType17.IsNotScreenableCriteriaItems != null)
                            {
                                foreach (var itemNotScreenable in criteriaType17.IsNotScreenableCriteriaItems)
                                {
                                    if (itemNotScreenable.IsOn)
                                    {
                                        filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaType17(itemNotScreenable.Id, filterId, filterGroupId, isReport, null);
                                        result.Add(filterCriteria);
                                    }
                                    //else
                                    //{   //delete filterCriteria
                                    //    if (isReport)
                                    //    {
                                    //        _filterCriteriaManager.DeleteFilterCriteriaByIdTemplateIdAndFilterId(itemNotScreenable.Id, filterId);
                                    //    }
                                    //}
                                }
                            }
                            break;

                        case 25:
                            filterGroupId = Guid.NewGuid();

                            var criteriaType25Definition = new CriteriaType25Dto();
                            var criteriaType25 = JsonConvert.DeserializeAnonymousType(item.ToString(), criteriaType25Definition);

                            if (criteriaType25.IsScreenableCriteriaItems != null)
                            {
                                foreach (var itemScreenable in criteriaType25.IsScreenableCriteriaItems)
                                {
                                    if (itemScreenable.Score >= 0)
                                    {
                                        filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaType25(itemScreenable.Id, filterId, filterGroupId, isReport, itemScreenable.Score);
                                        result.Add(filterCriteria);
                                    }
                                    //else
                                    //{
                                    //    if (isReport)
                                    //    {
                                    //        _filterCriteriaManager.DeleteFilterCriteriaByIdTemplateIdAndFilterId(itemScreenable.Id, filterId);
                                    //    }
                                    //}
                                }
                            }
                            if (criteriaType25.IsNotScreenableCriteriaItems != null)
                            {
                                foreach (var itemNotScreenable in criteriaType25.IsNotScreenableCriteriaItems)
                                {
                                    if (itemNotScreenable.IsOn)
                                    {
                                        filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaType25(itemNotScreenable.Id, filterId, filterGroupId, isReport, null);
                                        result.Add(filterCriteria);
                                    }
                                    //else
                                    //{   //delete filterCriteria
                                    //    if (isReport)
                                    //    {
                                    //        _filterCriteriaManager.DeleteFilterCriteriaByIdTemplateIdAndFilterId(itemNotScreenable.Id, filterId);
                                    //    }
                                    //}
                                }
                            }
                            break;
                    }
                }

                if (result == null)
                    response = Request.CreateResponse(HttpStatusCode.InternalServerError,
                               new { ErrorStatusCode = WebAPIGeneralErrorCodes.OperationFailed, FilterId = filterId, Details = result });
                else
                {
                    response = Request.CreateResponse(HttpStatusCode.Created, result);
                    PopulateResultOutputWithUpdatedCriteria(filterId);
                }
                return response;
            }
            catch (FilterCriteriaClaimNullException ex)
            {
                response = Request.CreateResponse(HttpStatusCode.Unauthorized,
                                                 new { ErrorStatusCode = WebAPIGeneralErrorCodes.AuthorizationFailed, FilterId = filterId, Details = result });
            }
            catch (UnknownUserException ex)
            {
                response = Request.CreateResponse(HttpStatusCode.Unauthorized,
                                                 new { ErrorStatusCode = WebAPIGeneralErrorCodes.UserNotFound, FilterId = filterId, Details = result });
            }
            catch (AuthorizationException ex)
            {
                response = Request.CreateResponse(HttpStatusCode.Unauthorized,
                                   new { ErrorStatusCode = WebAPIGeneralErrorCodes.AuthorizationFailed, FilterId = filterId, Details = result });
            }
            catch (CustomException ex)
            {
                response = Request.CreateResponse(HttpStatusCode.InternalServerError,
                                new { ErrorStatusCode = WebAPIGeneralErrorCodes.UnhandledException, FilterId = filterId, Details = result });
            }
            catch (Exception ex)
            {
                response = Request.CreateResponse(HttpStatusCode.InternalServerError,
                                new { ErrorStatusCode = WebAPIGeneralErrorCodes.UnhandledException, FilterId = filterId, Details = result });
            }
            return response;
        }

        private void PopulateResultOutputWithUpdatedCriteria(Guid filterId)
        {
            var allFilters =
                _filterCriteriaManager.GetAllFilterCriteriaByFilterId(filterId)
                    .Select(a => new CriteriaResultOutput()
                    {
                        CompaniesCount = (a.IsDataPoint) ? "Data Point" : "N/A",
                        Name = a.Name,
                        CriteriaType = a.CriteriaType,
                        CriteriaEntityField = a.CriteriaEntityField,
                        Order = a.Order,
                        IsValid = ResultIsValid.Valid,
                        SelectedValueInformation = a.SelectedValueInformation,
                        FilterCriteriaId = a.Id,
                        FilterCriteriaGroupId = a.FilterGroupId.GetValueOrDefault()
                    }).ToList();

            var serializedFilters = JsonConvert.SerializeObject(allFilters);
            _resultOutputCollection.DeleteMany(x => x.FilterId == filterId);
            ResultOutput resultOutput = new ResultOutput()
            {
                Id = Guid.Empty,
                IsValid = ResultIsValid.Valid,
                Criteria = serializedFilters,
                FilterId = filterId,
                CompanyId = Guid.Empty,
                CompanyName = string.Empty,
                CompanyNameLowerCase = string.Empty,
                CompanyNameUrlFriendly = string.Empty,
                CapitalIqId = 0
            };
            _resultOutputCollection.InsertOne(resultOutput);
        }

        [Route("")]
        public HttpResponseMessage Put([FromUri] Guid filterId, int criteriaType, Guid? criteriaLevel2Id, Guid? filterGroupId, [FromBody] object dto)
        {
            try
            {
                if (criteriaLevel2Id == null)
                    throw new ArgumentNullException();

                //Validates the call
                CriteriaLevel2 criteriaLevel2 = _companyScreening.GetCriteriaLevelTwo(criteriaLevel2Id.Value);
                ValidateShortName(criteriaLevel2.ShortName);

                var userName = this.GetCurrentUserName();

                var currentUser = _accountsRepository.GetUserByUsername(userName);
                if (currentUser == null)
                    throw new UnknownUserException(userName);

                Filter filter = _filterManager.LoadFilter(filterId, userName);
                FilterCriteria filterCriteria;
                bool isReport = filter.TargetType == 0 ? false : true;

                var result = new List<FilterCriteria>();
                switch (criteriaType)
                {
                    case 1:
                        var criteriaTypeOne = JsonConvert.DeserializeObject<CriteriaTypeOneDto>(dto.ToString());
                        filterCriteria = _filterCriteriaManager.UpdateCriteriaTypeOne(criteriaTypeOne.Id, filterId, criteriaTypeOne.MinValue, criteriaTypeOne.MaxValue);
                        result.Add(filterCriteria);
                        break;

                    case 2:
                        var criteriaTypeTwo = JsonConvert.DeserializeObject<CriteriaTypeTwoDto>(dto.ToString());
                        _filterCriteriaManager.DeleteFilterCriteriaByFilterGroupId(filterId, filterGroupId.Value);
                        foreach (var itemScreenable in criteriaTypeTwo.IsScreenableCriteriaItems)
                        {
                            if (itemScreenable.Score > 0)
                            {
                                filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeTwo(itemScreenable.Id, filterId, filterGroupId.Value, isReport, itemScreenable.Score);
                                result.Add(filterCriteria);
                            }
                        }
                        foreach (var itemNotScreenable in criteriaTypeTwo.IsNotScreenableCriteriaItems)
                        {
                            if (itemNotScreenable.IsOn)
                            {
                                filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeTwo(itemNotScreenable.Id, filterId, filterGroupId.Value, isReport, null);
                                result.Add(filterCriteria);
                            }
                        }
                        break;

                    case 3:
                        var criteriaTypeThree = JsonConvert.DeserializeObject<CriteriaTypeThreeDto>(dto.ToString());
                        _filterCriteriaManager.DeleteFilterCriteriaByFilterGroupId(filterId, filterGroupId.Value);

                        foreach (var itemScreenable in criteriaTypeThree.IsScreenableCriteriaItems)
                        {
                            if (itemScreenable.SelectedItems.Count > 0)
                            {
                                filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeThree(itemScreenable.Id, filterId, isReport, itemScreenable.SelectedItems, filterGroupId.Value);
                                result.Add(filterCriteria);
                            }
                        }

                        foreach (var itemNotScreenable in criteriaTypeThree.IsNotScreenableCriteriaItems)
                        {
                            if (itemNotScreenable.IsOn)
                            {
                                filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeThree(itemNotScreenable.Id, filterId, isReport, null, filterGroupId.Value);
                                result.Add(filterCriteria);
                            }
                        }
                        break;

                    case 4:
                        var criteriaTypeFourDefinition = new CriteriaTypeFourDto();
                        var criteriaTypeFour = JsonConvert.DeserializeAnonymousType(dto.ToString(), criteriaTypeFourDefinition);
                        criteriaTypeFour.CriteriaLevel2Id = criteriaLevel2Id.Value;
                        _filterCriteriaManager.DeleteFilterCriteriaByFilterGroupId(filterId, filterGroupId.Value);
                        ValidateClaimSymbol(criteriaTypeFour.ClaimSymbol);
                        foreach (var category in criteriaTypeFour.SelectedCategories)
                        {
                            result.Add(_filterCriteriaManager.AddAndUpdateCriteriaTypeFour(
                                category.Id,
                                filterId,
                                false,
                                category.CategoryOfInvolvement,
                                filterGroupId.Value,
                                category.CategorySymbol,
                                category.IsInvolvement,
                                category.IsSignificantOwnership,
                                category.RevenueRange,
                                category.Start,
                                category.Stop));
                        }
                        foreach (var itemNotScreenable in criteriaTypeFour.IsNotScreenableCriteriaItems)
                        {
                            if (itemNotScreenable.IsOn)
                            {
                                filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeFour(
                                    itemNotScreenable.Id,
                                    filterId,
                                    false,
                                    null, //CategoryOfInvolvement,
                                    filterGroupId.Value,
                                    null, //CategorySymbol,
                                    null, //IsInvolvement,
                                    null, //IsSignificantOwnership,
                                    null, //RevenueRange,
                                    null, //Start,
                                    null); //Stop)
                                result.Add(filterCriteria);
                            }
                        }
                        break;

                    case 5:
                        var criteriaTypeFive = JsonConvert.DeserializeObject<CriteriaTypeFiveDto>(dto.ToString());
                        _filterCriteriaManager.DeleteFilterCriteriaByFilterGroupId(filterId, filterGroupId.Value);
                        foreach (var itemScreenable in criteriaTypeFive.IsScreenableCriteriaItems)
                        {
                            if (itemScreenable.Score >= 0)
                            {
                                filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeFive(itemScreenable.Id, filterId, filterGroupId.Value, isReport, itemScreenable.Score);
                                result.Add(filterCriteria);
                            }
                        }
                        foreach (var itemNotScreenable in criteriaTypeFive.IsNotScreenableCriteriaItems)
                        {
                            if (itemNotScreenable.IsOn)
                            {
                                filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeFive(itemNotScreenable.Id, filterId, filterGroupId.Value, isReport, null);
                                result.Add(filterCriteria);
                            }
                        }
                        break;

                    case 6:
                        var criteriaTypeSix = JsonConvert.DeserializeObject<CriteriaTypeSixDto>(dto.ToString());
                        _filterCriteriaManager.DeleteFilterCriteriaByFilterGroupId(filterId, filterGroupId.Value);

                        if ((!isReport || criteriaTypeSix.Id != Guid.Empty) && !criteriaTypeSix.Removed)
                        {
                            filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeSix(criteriaTypeSix.Id,
                                filterId, filterGroupId.Value, isReport, criteriaTypeSix.MinValue, criteriaTypeSix.MaxValue);
                            result.Add(filterCriteria);
                        }

                        if (criteriaTypeSix.IsNotScreenableCriteriaItems != null)
                        {
                            foreach (var itemNotScreenable in criteriaTypeSix.IsNotScreenableCriteriaItems)
                            {
                                if (itemNotScreenable.IsOn)
                                {
                                    filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeSix(itemNotScreenable.Id, filterId, filterGroupId.Value, isReport, null, null);
                                    result.Add(filterCriteria);
                                }
                            }
                        }
                        break;

                    case 7:
                        var criteriaTypeSeven = JsonConvert.DeserializeObject<CriteriaTypeSevenDto>(dto.ToString());

                        _filterCriteriaManager.DeleteFilterCriteriaByFilterGroupId(filterId, filterGroupId.Value);

                        foreach (var itemScreenable in criteriaTypeSeven.IsScreenableCriteriaItems)
                        {
                            if (itemScreenable.SelectedItems.Count > 0)
                            {
                                ValidateGlobalCompact(itemScreenable.SelectedItems);
                                filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeSeven(itemScreenable.Id, filterId, filterGroupId.Value, isReport, itemScreenable.SelectedItems);
                                result.Add(filterCriteria);
                            }
                        }
                        foreach (var itemNotScreenable in criteriaTypeSeven.IsNotScreenableCriteriaItems)
                        {
                            if (itemNotScreenable.IsOn)
                            {
                                filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeFive(itemNotScreenable.Id, filterId, filterGroupId.Value, isReport, null);
                                result.Add(filterCriteria);
                            }
                        }
                        break;

                    case 8:
                        var criteriaTypeEight = JsonConvert.DeserializeObject<CriteriaTypeEightDto>(dto.ToString());
                        _filterCriteriaManager.DeleteFilterCriteriaByFilterGroupId(filterId, filterGroupId.Value);
                        foreach (var itemScreenable in criteriaTypeEight.IsScreenableCriteriaItems)
                        {
                            if (itemScreenable.Score > 0)
                            {
                                filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeEight(itemScreenable.Id, filterId, filterGroupId.Value, isReport, itemScreenable.Score);
                                result.Add(filterCriteria);
                            }
                        }
                        foreach (var itemNotScreenable in criteriaTypeEight.IsNotScreenableCriteriaItems)
                        {
                            if (itemNotScreenable.IsOn)
                            {
                                filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeEight(itemNotScreenable.Id, filterId, filterGroupId.Value, isReport, null);
                                result.Add(filterCriteria);
                            }
                        }
                        break;

                    case 9:
                        var criteriaTypeNine = JsonConvert.DeserializeObject<CriteriaTypeNineDto>(dto.ToString());
                        _filterCriteriaManager.DeleteFilterCriteriaByFilterGroupId(filterId, filterGroupId.Value);
                        foreach (var itemScreenable in criteriaTypeNine.IsScreenableCriteriaItems)
                        {
                            if (itemScreenable.Score > 0)
                            {
                                filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeNine(itemScreenable.Id, filterId, filterGroupId.Value, isReport, itemScreenable.Score);
                                result.Add(filterCriteria);
                            }
                        }
                        foreach (var itemNotScreenable in criteriaTypeNine.IsNotScreenableCriteriaItems)
                        {
                            if (itemNotScreenable.IsOn)
                            {
                                filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeNine(itemNotScreenable.Id, filterId, filterGroupId.Value, isReport, null);
                                result.Add(filterCriteria);
                            }
                        }
                        break;

                    case 10:
                        var criteriaTypeTen = JsonConvert.DeserializeObject<CriteriaTypeTenDto>(dto.ToString());
                        _filterCriteriaManager.DeleteFilterCriteriaByFilterGroupId(filterId, filterGroupId.Value);
                        foreach (var itemNotScreenable in criteriaTypeTen.IsNotScreenableCriteriaItems)
                        {
                            if (itemNotScreenable.IsOn)
                            {
                                filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaTypeTen(itemNotScreenable.Id, filterId, filterGroupId.Value, isReport/*, null*/);
                                result.Add(filterCriteria);
                            }
                        }
                        break;

                    case 16:
                        var criteriaType16 = JsonConvert.DeserializeObject<CriteriaType16Dto>(dto.ToString());
                        _filterCriteriaManager.DeleteFilterCriteriaByFilterGroupId(filterId, filterGroupId.Value);

                        if (!isReport && !criteriaType16.Removed)
                        {
                            filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaType16(criteriaType16.Id,
                                filterId, filterGroupId.Value, isReport, criteriaType16.MinValue, criteriaType16.MaxValue);
                            result.Add(filterCriteria);
                        }

                        if (criteriaType16.IsNotScreenableCriteriaItems != null)
                        {
                            foreach (var itemNotScreenable in criteriaType16.IsNotScreenableCriteriaItems)
                            {
                                if (itemNotScreenable.IsOn)
                                {
                                    filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaType16(itemNotScreenable.Id, filterId, filterGroupId.Value, isReport, null, null);
                                    result.Add(filterCriteria);
                                }
                            }
                        }
                        break;

                    case 17:
                        var criteriaType17 = JsonConvert.DeserializeObject<CriteriaType17Dto>(dto.ToString());
                        _filterCriteriaManager.DeleteFilterCriteriaByFilterGroupId(filterId, filterGroupId.Value);
                        foreach (var itemScreenable in criteriaType17.IsScreenableCriteriaItems)
                        {
                            if (itemScreenable.Score >= 0)
                            {
                                filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaType17(itemScreenable.Id, filterId, filterGroupId.Value, isReport, itemScreenable.Score);
                                result.Add(filterCriteria);
                            }
                        }
                        break;
                    case 25:
                        var criteriaType25 = JsonConvert.DeserializeObject<CriteriaType25Dto>(dto.ToString());
                        _filterCriteriaManager.DeleteFilterCriteriaByFilterGroupId(filterId, filterGroupId.Value);
                        foreach (var itemScreenable in criteriaType25.IsScreenableCriteriaItems)
                        {
                            if (itemScreenable.Score >= 0)
                            {
                                filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaType25(itemScreenable.Id, filterId, filterGroupId.Value, isReport, itemScreenable.Score);
                                result.Add(filterCriteria);
                            }
                        }
                        foreach (var itemNotScreenable in criteriaType25.IsNotScreenableCriteriaItems)
                        {
                            if (itemNotScreenable.IsOn)
                            {
                                filterCriteria = _filterCriteriaManager.AddAndUpdateCriteriaType25(itemNotScreenable.Id, filterId, filterGroupId.Value, isReport, null);
                                result.Add(filterCriteria);
                            }
                        }
                        break;
                }

                if (result == null)
                    return Request.CreateResponse(HttpStatusCode.InternalServerError,
                               new { ErrorStatusCode = WebAPIGeneralErrorCodes.OperationFailed, FilterId = filterId, Details = dto });

                return Request.CreateResponse(HttpStatusCode.Created, result);
            }
            catch (FilterCriteriaClaimNullException ex)
            {
                return Request.CreateResponse(HttpStatusCode.Unauthorized,
                                                 new { ErrorStatusCode = WebAPIGeneralErrorCodes.AuthorizationFailed, FilterId = filterId, Details = dto });
            }
            catch (UnknownUserException ex)
            {
                return Request.CreateResponse(HttpStatusCode.Unauthorized,
                                                 new { ErrorStatusCode = WebAPIGeneralErrorCodes.UserNotFound, FilterId = filterId, Details = dto });
            }
            catch (AuthorizationException ex)
            {
                return Request.CreateResponse(HttpStatusCode.Unauthorized,
                                   new { ErrorStatusCode = WebAPIGeneralErrorCodes.AuthorizationFailed, FilterId = filterId, Details = dto });
            }
            catch (CustomException ex)
            {
                return Request.CreateResponse(HttpStatusCode.InternalServerError,
                                new { ErrorStatusCode = WebAPIGeneralErrorCodes.UnhandledException, FilterId = filterId, Details = dto });
            }
            catch (Exception ex)
            {
                return Request.CreateResponse(HttpStatusCode.InternalServerError,
                                new { ErrorStatusCode = WebAPIGeneralErrorCodes.UnhandledException, FilterId = filterId, Details = dto });
            }
        }

        [Route("{id}")]
        public HttpResponseMessage Delete(Guid filterId, Guid id)
        {
            try
            {
                if (!_claimsChecker.ValidateRoute(this))
                    throw new FilterCriteriaClaimNullException();

                _filterCriteriaManager.DeleteFilterCriteriaById(id);
                PopulateResultOutputWithUpdatedCriteria(filterId);

                return Request.CreateResponse(HttpStatusCode.OK);
            }
            catch (FilterCriteriaClaimNullException)
            {
                return Request.CreateResponse(HttpStatusCode.Forbidden);
            }
            catch (Exception)
            {
                return Request.CreateResponse(HttpStatusCode.InternalServerError, new { ErrorCode = 1010 });
            }
        }

        [Route("")]
        public HttpResponseMessage Patch([FromUri] Guid filterId, Guid filterCriteriaId, Guid? filterGroupId)
        {
            try
            {
                if (!_claimsChecker.ValidateRoute(this))
                    throw new FilterCriteriaClaimNullException();

                if (filterGroupId == Guid.Empty)
                {
                    _filterCriteriaManager.DeleteFilterCriteriaById(filterCriteriaId);
                }
                else
                {
                    _filterCriteriaManager.DeleteFilterCriteriaGroup(filterId, filterCriteriaId, filterGroupId);
                }
                return Request.CreateResponse(HttpStatusCode.OK);
            }
            catch (FilterCriteriaClaimNullException)
            {
                return Request.CreateResponse(HttpStatusCode.Forbidden);
            }
            catch (Exception)
            {
                return Request.CreateResponse(HttpStatusCode.InternalServerError, new { ErrorCode = 1010 });
            }
        }

        /// <summary>
        /// Validate by Short Name.
        /// PI and Global Compact Compliance use a different system for validate claim.
        /// </summary>
        /// <param name="shortName"></param>
        private void ValidateShortName(string shortName)
        {
            switch (shortName)
            {
                case "PI":
                case "SP":
                case "Global Compact Compliance":
                    break;

                default:
                    if (!_claimsChecker.ValidateCriteria(this, shortName, null))
                        throw new FilterCriteriaClaimNullException();
                    break;
            }
        }

        /// <summary>
        /// Validate by Claim Symbol. Used for Criteria Type 4 - Product Involvement
        /// </summary>
        /// <param name="claimSymbol"></param>
        private void ValidateClaimSymbol(string claimSymbol)
        {
            if (!_claimsChecker.ValidateCriteria(this, null, claimSymbol))
                throw new FilterCriteriaClaimNullException();
        }

        /// <summary>
        /// Validate global compact selected items
        /// <list type="string">
        /// <item>
        /// <description>0: Compliant - there is not claim validation for this case</description>
        /// </item>
        /// <item>
        /// <description>1: Non-compliant - validation on shortName "gccsnc" </description>
        /// </item>
        /// <item>
        /// <description>2: Watchlist - validation on shortName "gccswl"</description>
        /// </item>
        /// </list>
        /// </summary>
        /// <param name="selectedItems">Accepted values: 0, 1, 2</param>
        private void ValidateGlobalCompact(IEnumerable<string> selectedItems)
        {
            foreach (var item in selectedItems)
            {
                switch (item)
                {
                    case "1":
                        if (!_claimsChecker.ValidateCriteria(this, "gccsnc", null))
                            throw new FilterCriteriaClaimNullException();
                        break;

                    case "2":
                        if (!_claimsChecker.ValidateCriteria(this, "gccswl", null))
                            throw new FilterCriteriaClaimNullException();
                        break;
                }
            }
        }
    }
}
